package top.wineye.spring.ioc.dependency;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import top.wineye.model.User;
import top.wineye.model.annotation.Super;

import java.util.Map;

public class DependencyLookup {

    /**
     * 实时查找
     * 查找集合
     * 延迟查找
     *  * 返回一个代理对象，需要用到 bean 的时候再去获取 bean
     * @param args r
     */

    public static void main(String[] args) {
        BeanFactory beanFactory =
                new ClassPathXmlApplicationContext("classpath:META-INF/dependency-lookup-context.xml");

        // 实时查找

        // 根据 bean name 查找
        realTimeLookupByName(beanFactory);
        // 根据 type 查到单个 bean
        realTimeLookupByType(beanFactory);
        // 根据 type 查找 bean 集合
        realTimeLookupMultiByType(beanFactory);
        // 根据 annotation 查找
        realtimeLookupByAnnotation(beanFactory);

        // 延迟查找
        lazyLookup(beanFactory);
    }

    private static void realtimeLookupByAnnotation(BeanFactory bf) {
        if (bf instanceof ListableBeanFactory) {
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory) bf;
            Map<String, Object> bean = listableBeanFactory.getBeansWithAnnotation(Super.class);
            System.out.println("get by annotation @Super : " + bean.values());
        }
    }

    private static void realTimeLookupByName(BeanFactory bf) {
        User user = (User) bf.getBean("user");
        System.out.println("real time lookup by name user: " + user);
    }

    private static void realTimeLookupByType(BeanFactory bf) {
        // 当有两个相同 Type 的 bean, 通过 type 直接获取就会报错
        // 需要通过 primary 指定优先获取
        User user = bf.getBean(User.class);
        System.out.println("real time lookup by type User.class: " + user);
    }

    private static void realTimeLookupMultiByType(BeanFactory bf) {
        if (bf instanceof ListableBeanFactory) {
            ListableBeanFactory listableBeanFactory = (ListableBeanFactory) bf;
            Map<String, User> beansOfType = listableBeanFactory.getBeansOfType(User.class);
            System.out.println(beansOfType.values());
        }

    }

    /*
        ObjectFactoryCreatingFactoryBean
     */
    private static void lazyLookup(BeanFactory beanFactory) {
        Object o = beanFactory.getBean("objectFactory");
        if (o instanceof ObjectFactory) { // 为什么判断了还是 unchecked cast ?
            ObjectFactory<User> objectFactory = (ObjectFactory<User>) o;
            System.out.println("lazy lookup: " + objectFactory.getObject());
        }
    }





}
